#ifndef _QUEUE_HPP_
#define _QUEUE_HPP_

#include <deque>
#include "lock.hpp"
#include "condition.hpp"

namespace mina
{
	namespace thread
	{
		template <typename _T>
			class Queue
			{
				public :
					Queue()
						: _lock(),
						  _cond(),
						  _queue_size(0)
					{
					}
					~Queue() {}

					void put(const _T & val);
					void get(_T & val);

					size_t size() const { return _queue_size; }
					bool empty() const { return (0 == _queue_size); }
				private :
					Lock _lock;
					Condition _cond;

					size_t _queue_size;
					std::deque<_T> _queue;		
			};

		template <typename _T>
			void Queue<_T>::put(const _T& val)
			{
				_lock.lock();
				bool empty = (_queue_size == 0);
				_queue.push_back(val);
				++ _queue_size;
				if (empty)
				{
					_cond.signal();
				}
				_lock.unlock();
			}

		template <typename _T>
			void Queue<_T>::get(_T & val)
			{
				_lock.lock();

				while (_queue.empty())
				{
					_cond.wait(_lock);
				}

				val = _queue.front();
				_queue.pop_front();
				-- _queue_size;

				_lock.unlock();
			}

	}
}

#endif

